// Copyright Epic Games, Inc. All Rights Reserved.

#include "LyraControllerDisconnectedScreen.h"

#include "Components/HorizontalBox.h"
#include "CommonButtonBase.h"
#include "CommonUISettings.h"
#include "GameFramework/InputDeviceSubsystem.h"
#include "GenericPlatform/GenericPlatformApplicationMisc.h"
#include "GenericPlatform/GenericPlatformInputDeviceMapper.h"
#include "ICommonUIModule.h"
#include "NativeGameplayTags.h"
#include "LyraLogChannels.h"

#if WITH_EDITOR
#include "CommonUIVisibilitySubsystem.h"
#endif	// WITH_EDITOR

#include UE_INLINE_GENERATED_CPP_BY_NAME(LyraControllerDisconnectedScreen)

// 定义平台特性标签：具有严格控制器配对
UE_DEFINE_GAMEPLAY_TAG_STATIC(TAG_Platform_Trait_Input_HasStrictControllerPairing, "Platform.Trait.Input.HasStrictControllerPairing");

/**
 * 构造函数
 * @param ObjectInitializer 对象初始化器
 */
ULyraControllerDisconnectedScreen::ULyraControllerDisconnectedScreen(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
	// 默认情况下，只有具有严格配对要求的平台需要此按钮
	PlatformSupportsUserChangeTags.AddTag(TAG_Platform_Trait_Input_HasStrictControllerPairing);
}

/**
 * 当控件激活时调用
 * 设置切换用户按钮的可见性
 */
void ULyraControllerDisconnectedScreen::NativeOnActivated()
{
	// 调用父类实现
	Super::NativeOnActivated();

	// 检查切换用户水平框是否存在
	if (!HBox_SwitchUser)
	{
		// 记录错误日志
		UE_LOG(LogLyra, Error, TEXT("Unable to find HBox_SwitchUser on Widget %s"), *GetNameSafe(this));
		return;
	}

	// 检查切换用户按钮是否存在
	if (!Button_ChangeUser)
	{
		// 记录错误日志
		UE_LOG(LogLyra, Error, TEXT("Unable to find Button_ChangeUser on Widget %s"), *GetNameSafe(this));
		return;
	}

	// 默认隐藏切换用户水平框
	HBox_SwitchUser->SetVisibility(ESlateVisibility::Collapsed);
	// 默认隐藏切换用户按钮
	Button_ChangeUser->SetVisibility(ESlateVisibility::Hidden);

	// 如果应该显示切换用户按钮
	if (ShouldDisplayChangeUserButton())
	{
		// 获取"未配对"输入设备的平台用户。并非所有平台都支持此功能
		const FPlatformUserId UnpairedUserId = IPlatformInputDeviceMapper::Get().GetUserForUnpairedInputDevices();
		// 如果未配对用户有效
		if (UnpairedUserId.IsValid())
		{
			// 显示切换用户水平框
			HBox_SwitchUser->SetVisibility(ESlateVisibility::SelfHitTestInvisible);
			// 显示切换用户按钮
			Button_ChangeUser->SetVisibility(ESlateVisibility::SelfHitTestInvisible);
		}		
	}

	// 绑定切换用户按钮的点击事件
	Button_ChangeUser->OnClicked().AddUObject(this, &ThisClass::HandleChangeUserClicked);
}

/**
 * 返回是否应显示切换用户按钮
 * @return 如果需要显示切换用户按钮则返回true
 */
bool ULyraControllerDisconnectedScreen::ShouldDisplayChangeUserButton() const
{
	// 检查通用UI设置中的平台特性是否包含所有需要的标签
	bool bRequiresChangeUserButton = ICommonUIModule::GetSettings().GetPlatformTraits().HasAll(PlatformSupportsUserChangeTags);

	// 检查在编辑器中可能模拟的标签
#if WITH_EDITOR
	const FGameplayTagContainer& PlatformEmulationTags = UCommonUIVisibilitySubsystem::Get(GetOwningLocalPlayer())->GetVisibilityTags();
	// 如果编辑器中的平台模拟标签包含所有需要的标签，也要求显示切换用户按钮
	bRequiresChangeUserButton |= PlatformEmulationTags.HasAll(PlatformSupportsUserChangeTags);
#endif	// WITH_EDITOR

	// 返回是否需要显示切换用户按钮
	return bRequiresChangeUserButton;
}

/**
 * 处理切换用户按钮点击事件
 */
void ULyraControllerDisconnectedScreen::HandleChangeUserClicked()
{
	// 确保应该显示切换用户按钮
	ensure(ShouldDisplayChangeUserButton());

	// 记录切换用户请求日志
	UE_LOG(LogLyra, Log, TEXT("[%hs] Change user requested!"), __func__);

	// 获取所属玩家的平台用户ID
	const FPlatformUserId OwningPlayerId = GetOwningLocalPlayer()->GetPlatformUserId();
	// 获取该用户的主要输入设备ID
	const FInputDeviceId DeviceId = IPlatformInputDeviceMapper::Get().GetPrimaryInputDeviceForUser(OwningPlayerId);

	// 显示平台用户选择器
	FGenericPlatformApplicationMisc::ShowPlatformUserSelector(
		DeviceId, // 设备ID
		EPlatformUserSelectorFlags::Default, // 默认标志
		[this](const FPlatformUserSelectionCompleteParams& Params) // 完成回调
		{
			// 用户选择完成后处理
			HandleChangeUserCompleted(Params);
		});
}

/**
 * 处理用户切换完成
 * @param Params 用户选择完成参数
 */
void ULyraControllerDisconnectedScreen::HandleChangeUserCompleted(const FPlatformUserSelectionCompleteParams& Params)
{
	// 记录用户切换完成日志
	UE_LOG(LogLyra, Log, TEXT("[%hs] User change complete!"), __func__);

	// TODO: 在此处处理游戏中的任何用户更改逻辑
}